package org.balthie.demo.jdk.nio.reactor.multiplyThread;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MthreadHandler implements Runnable {

	private static final int INPUT_SIZE = 1024;
	private static final int SEND_SIZE = 1024;

	final SocketChannel channel;
	final SelectionKey selectionKey;

	static final int READING = 0, SENDING = 1;
	static final int PROCESSING = 3;
	int state = READING;

	static ExecutorService pool = Executors.newFixedThreadPool(2);

	ByteBuffer input = ByteBuffer.allocate(INPUT_SIZE);
	ByteBuffer output = ByteBuffer.allocate(SEND_SIZE);

	MthreadHandler(Selector selector, SocketChannel c) throws IOException {
		channel = c;
		
		c.configureBlocking(false);
		// Optionally try first read now
		selectionKey = channel.register(selector, 0);
		// 将Handler作为callback对象
		selectionKey.attach(this);
		// 第二步,注册Read就绪事件
		selectionKey.interestOps(SelectionKey.OP_READ);
		
//		https://www.zhihu.com/question/389599681/answer/1175262830
//		虽然当前没有阻塞在select()上，但是会影响下一次调用select()立即返回
		selector.wakeup();
	}

	boolean inputIsComplete() {
		/* ... */
		return false;
	}

	boolean outputIsComplete() {
		/* ... */
		return false;
	}

	public void run() {
		try {
			if (state == READING) {
				read();
			} else if (state == SENDING) {
				send();
			}
		} catch (IOException ex) {
			/* ... */ }
	}

	synchronized void read() throws IOException {
		// ...
		channel.read(input);
		if (inputIsComplete()) {
			state = PROCESSING;
			// 使用线程pool异步执行
			pool.execute(new Processer(selectionKey));
		}
	}

	void send() throws IOException {
		channel.write(output);
		// write完就结束了, 关闭select key
		if (outputIsComplete()) {
			selectionKey.cancel();
		}
	}
}
